package org.dh2580.netty.demo.aio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.util.concurrent.CountDownLatch;

/**
 * @Author: hao.deng
 * @Date: 2019/3/27-下午1:07
 */
public class TimeClient {
    public static void main(String[] args) throws IOException {
        new Thread(new AsyncTimeClientHandler("127.0.0.1", 8080)).start();
    }

    public static class AsyncTimeClientHandler implements Runnable, CompletionHandler<Void, AsyncTimeClientHandler> {
        private AsynchronousSocketChannel socketChannel;

        private String host;
        private int port;

        private CountDownLatch latch;

        public AsyncTimeClientHandler(String host, int port) throws IOException {
            this.host = host;
            this.port = port;

            socketChannel = AsynchronousSocketChannel.open();
        }

        @Override
        public void run() {
            latch = new CountDownLatch(1);
            socketChannel.connect(new InetSocketAddress(host, port), this, this);

            try {
                latch.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }

        @Override
        public void completed(Void result, AsyncTimeClientHandler attachment) {
            byte[] req = "QUERY TIME ORDER".getBytes();
            ByteBuffer writeBuffer = ByteBuffer.allocate(req.length);
            writeBuffer.put(req);
            writeBuffer.flip();

            socketChannel.write(writeBuffer, writeBuffer, new CompletionHandler<Integer, ByteBuffer>() {
                @Override
                public void completed(Integer result, ByteBuffer attachment) {
                    if (writeBuffer.hasRemaining()) {
                        socketChannel.write(writeBuffer, writeBuffer, this);
                    } else {
                        ByteBuffer readBuffer = ByteBuffer.allocate(1024);
                        socketChannel.read(readBuffer, readBuffer, new CompletionHandler<Integer, ByteBuffer>() {
                            @Override
                            public void completed(Integer result, ByteBuffer attachment) {
                                attachment.flip();
                                byte[] bytes = new byte[attachment.remaining()];
                                String body = new String(bytes);

                                System.out.println("Now is " + body);

                                latch.countDown();
                            }

                            @Override
                            public void failed(Throwable exc, ByteBuffer attachment) {
                                exc.printStackTrace();
                                try {
                                    socketChannel.close();
                                    latch.countDown();
                                } catch (IOException e) {
                                    e.printStackTrace();
                                }
                            }
                        });
                    }
                }

                @Override
                public void failed(Throwable exc, ByteBuffer attachment) {
                    try {
                        exc.printStackTrace();
                        socketChannel.close();
                        latch.countDown();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }

                }
            });
        }

        @Override
        public void failed(Throwable exc, AsyncTimeClientHandler attachment) {
            try {
                exc.printStackTrace();
                socketChannel.close();
                latch.countDown();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}
